home *** CD-ROM | disk | FTP | other *** search
- /* tape.c - handle (tape) archive for the Tar program (see file tar.c)
- * Author: T.V.Shaporev
- * Creation date: 14 Dec 1990
- * Contains both MS-DOS and UNIX specific codes
- * Called by many functions - see files tar.c store.c extract.c
- */
- #include <stdio.h>
- #include <errno.h>
-
- #include "sysup.h"
- #include "modern.h"
- #include "zippipe.h"
- #include "lzwhead.h"
- #include "compress.h"
- #include "define.h"
-
- #ifdef MODERN
- # include <string.h>
- # include <stdlib.h>
- #else
- # ifdef M_XENIX
- # include <string.h>
- # else
- int strlen();
- char *strcpy(), *strncpy(), *mktemp();
- # endif
- extern char *sys_errlist[];
- extern int sys_nerr;
- #endif
- #ifdef MSDOS
- # include <io.h>
- # ifdef __TURBOC__
- # include <dir.h>
- # else
- # include <direct.h>
- # endif
- #else
- int creat(), open(), read(), write(), close();
- long lseek();
- #endif
-
- static int n_read, mblock, nblock, rblock, wblock;
- static int indread, indwrite;
- static char rerror[] = "Tar: tape read error\n";
-
- static int sread __ARGS__((char*, int));
- static int swrite __ARGS__((char*, int));
- static int sback __ARGS__((int));
- #ifdef MSDOS
- extern int dread __ARGS__((char*, int));
- extern int dwrite __ARGS__((char*, int));
- extern int dback __ARGS__((int));
-
- extern int qparse __ARGS__((char*));
- extern int qbegin __ARGS__((void));
- extern int qread __ARGS__((char*, int));
- extern int qwrite __ARGS__((char*, int));
- extern int qback __ARGS__((int));
- #endif
- static void talign __ARGS__((long));
-
- void printbs __ARGS__((int));
-
- static void psyserr __ARGS__((void))
- {
- if (errno < sys_nerr) (void)fprintf(myout, "%s\n", sys_errlist[errno]);
- else (void)fprintf(myout, "error %d\n", errno);
- }
-
- static int sread(buf, n) /* regular file reading */
- char *buf; register n;
- {
- if ((n = read(handle, buf, n)) == -1) {
- (void)fprintf(myout, "Tar: archive read error: "); psyserr();
- }
- return n;
- }
-
- static int swrite(buf, n) /* regular file writing */
- char *buf; register n;
- {
- if (write(hwrite, buf, n) != n) {
- (void)fprintf(myout, "Tar: archive write error: ");
- #ifdef MSDOS
- if (n != -1) (void)fprintf(myout,"disk full\n"); else
- #endif
- psyserr();
- n = -1;
- }
- return n;
- }
-
- static int sback(n)
- register n;
- {
- return lseek(handle, (long)-BLKSIZE*n, 1) < 0 ? -1 : n;
- }
-
- #ifdef USE_COMPRESS
- static int zwrite __ARGS__((char*, int));
-
- static int zwrite(buf, n) /* compressed file writing */
- char *buf; register n;
- {
- cpiece(buf, n); return n;
- }
- #endif
-
- static int gread __ARGS__((char*, int));
- static int gwrite __ARGS__((char*, int));
-
- static int gread(buf, n) /* deflated file reading */
- char *buf; register n;
- {
- if ((n = unzread(buf, n)) == -1) {
- (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
- }
- return n;
- }
-
- static int gwrite(buf, n) /* deflated file reading */
- char *buf; register n;
- {
- if ((n = zipwrite(buf, n)) == -1) {
- (void)fprintf(myout, "Tar: unzip error: %s\n", ziperrlist[ziperror]);
- }
- return n;
- }
-
- static int ziperr __ARGS__((void))
- {
- (void)fprintf(stderr, "Tar: zip error: %s\n", ziperrlist[ziperror]);
- return ziperror == ZNOMEM ? ESMALL : ERINIT;
- }
-
- #ifndef USE_COMPRESS
- static int twofault __ARGS__((char*, int));
-
- /*ARGSUSED2*/ static int twofault(buf, n)
- char *buf; register n;
- {
- #ifdef __TURBOC__
- (void)buf; (void)n;
- #endif
- return -1;
- }
- #endif
-
- /*ARGSUSED*/ static int onefault(n)
- int n;
- {
- #ifdef __TURBOC__
- (void)n;
- #endif
- return -1;
- }
-
- static int (*pread) __ARGS__((char*, int)) = sread;
- static int (*pwrite)__ARGS__((char*, int)) = swrite;
- static int (*pback) __ARGS__((int)) = sback;
-
- static int (*lread) __ARGS__((char*, int)) = sread;
- static int (*lwrite)__ARGS__((char*, int)) = swrite;
- static int (*lback) __ARGS__((int)) = sback;
- static int (*rcount)__ARGS__((char*, int)) = sread;
-
- static int cntread __ARGS__((char*, int));
-
- int cntread(buf, n)
- char *buf; register n;
- {
- if ((n = (*rcount)(buf, n)) != -1) {
- allblock += (BLKSIZE-1 + (unsigned)n) / BLKSIZE;
- }
- return n;
- }
-
- static void talign(i)
- long i;
- {
- if (i % BLKSIZE) {
- (void)fprintf(myout, "Tar: tape blocksize error\n");
- if (!i_flag) done(ERREAD);
- }
- }
-
- void printbs(bs)
- int bs;
- {
- if (v_flag) (void)fprintf(myout, "Tar: blocksize = %d\n", bs);
- }
-
- static void wrerror __ARGS__((void))
- {
- (void)fprintf(myout, "Tar: tape write error\n");
- done(EWRITE);
- }
-
- static int indget;
- static int eof_already = FALSE;
- static int got_length;
- static int indput;
-
- static int getbyte __ARGS__(( void ))
- {
- if (eof_already) goto end;
- if (indget >= got_length) {
- if (pksize == 0) {
- if ((got_length = (*lread)(pk_inp, MAXBLOCK*BLKSIZE)) < 0) goto err;
- if ((sa.st_mode & S_IFMT) == S_IFCHR) talign((long)got_length);
- pksize = got_length;
- if ((pksize % BLKSIZE) == 0) printbs(pksize/BLKSIZE);
- } else {
- if (got_length < pksize || got_length % BLKSIZE) goto end;
- if ((got_length = (*lread)(pk_inp, pksize)) < 0) goto err;
- }
- if (got_length < 1) goto end;
- indget = 0;
- }
- return ((unsigned char *)pk_inp)[indget++];
- err:
- (void)fprintf(myout, rerror);
- done(ERREAD);
- end:
- eof_already = TRUE;
- return EOF;
- }
-
- static void pkflush __ARGS__((void))
- {
- #ifdef MSDOS
- if (devtype != DEV_FILE && devtype != DEV_FLOP)
- #else
- if (!isfile)
- #endif
- while (indput < pksize) pk_out[indput++] = 0;
-
- if ((*lwrite)(pk_out, indput) < indput) wrerror();
- indput = 0;
- }
-
- static void putbyte(c)
- register c;
- {
- if (indput >= pksize) {
- #ifndef pksize
- /* Buffer size must not be less then 512 bytes, so we */
- /* can wait for blocksize will be detected by reading */
- if (indput < BLKSIZE) goto put;
- if (pksize < BLKSIZE) pksize = BLKSIZE;
- #endif
- pkflush();
- }
- put:
- pk_out[indput++] = c;
- }
-
- int initape(name)
- char *name;
- {
- #ifdef UNIX
- char tn[10]; register char *n;
- #endif
- #ifdef MSDOS
- register k;
- #endif
-
- handle = -1;
-
- pread = lread = sread;
- pwrite = lwrite = swrite;
- pback = lback = sback;
-
- if (name && name[0]=='-' && name[1]==0) {
- if ((a_flag && !c_flag) || d_flag) {
- (void)fprintf(stderr, "Tar: can\'t update stdout\n");
- return ERRARG;
- }
- #ifdef myinp
- if (j_flag
- # ifndef MSDOS
- || w_flag
- # endif
- ) {
- (void)fprintf(stderr, "Tar: input must be free\n");
- return ERRARG;
- }
- #endif
- handle = a_flag ? /* stdout */ 1 : /* stdin */ 0;
- myout = stderr;
- } else {
- #ifdef UNIX
- if (name && name[0]) {
- n = name;
- } else {
- n = strcpy(tn, "/dev/mt0"); tn[7] = (ndrive & 7) | '0';
- }
- handle = c_flag ? creat(n, 0666) :
- open (n, a_flag && !d_flag ? O_RDWR : O_RDONLY);
- if (handle < 0) {
- cantopen(n); return ERINIT;
- }
- #endif
-
- #ifdef MSDOS
- if (!name || !name[0]) {
- devtype = DEV_FLOP;
- inidisk();
- } else if ((k=qparse(name)) != FALSE) {
- if (k != TRUE) return ERRARG;
- pread = lread = qread;
- pwrite = lwrite = qwrite;
- pback = lback = qback;
- devtype = DEV_QIC2;
- } else {
- if (!k_flag && defdev(name)==0) k_flag = TRUE;
- if (k_flag) {
- devtype = DEV_FLOP;
- inidisk();
- } else {
- handle = open(name, !a_flag || d_flag ? O_RDONLY+O_BINARY :
- c_flag ? O_CREAT+O_TRUNC+O_WRONLY+O_BINARY :
- O_RDWR+O_BINARY,
- S_IREAD+S_IWRITE);
- if (handle < 0) {
- cantopen(name); return ERINIT;
- }
- devtype = DEV_FILE;
- }
- }
- if (devtype == DEV_FLOP) {
- pread = lread = dread;
- pwrite = lwrite = dwrite;
- pback = lback = dback;
- }
- #endif
- }
- if (t_flag) {/* yet another redirection */
- rcount = lread; pread = lread = cntread; allblock = 0L;
- }
- if (!cblock & c_flag) printbs(cblock = MAXBLOCK);
- if (handle < 0 || fstat(handle, &sa) != 0) sa.st_mode = S_IFBLK;
- hwrite = handle;
- return CORRECT;
- }
-
- static void swapbufs __ARGS__((void))
- {
- register j; register char *p;
-
- p = pk_inp; pk_inp = io_buf; io_buf = p;
- p = pk_out; pk_out = io_2nd; io_2nd = p;
-
- j = pksize;
- pksize = BLKSIZE*cblock;
- cblock = j/BLKSIZE;
- }
-
- int runtape()
- {
- #ifdef MSDOS
- if (devtype == DEV_QIC2) {
- if (qbegin()) return ERINIT;
- }
- #endif
- if (pktype == PKpLZW) {
- /* Redirect IO */
- pread = dpiece;
- #ifdef USE_COMPRESS
- pwrite = zwrite;
- #else
- pwrite = twofault;
- #endif
- pback = onefault;
-
- swapbufs();
-
- if (x_flag || t_flag || d_flag) {
- register j;
-
- indget = got_length = pksize;
- if ((j=dbegin(getbyte))!=0) {
- if (j < 0) {
- outmem(stderr);
- return ESMALL;
- } else {
- (void)fprintf(stderr,
- "Tar: archive is not in compresssed format\n");
- return ERINIT;
- }
- }
- }
- if (a_flag || d_flag) {
- #ifdef USE_COMPRESS
- if (cbegin(pklevel, putbyte, 0x7fffffffL) != pklevel) {
- outmem(stderr);
- return ESMALL;
- }
- #else
- (void)fprintf(stderr,
- "Tar: this restricted version does not support LZW compression\n");
- return ERRARG;
- #endif
- }
- #ifdef USE_COMPRESS
- indput = 0;
- #endif
- } else if (pktype == PKZIP) {
- /* Redirect IO */
- pread = gread; pwrite = gwrite; pback = onefault;
- swapbufs();
-
- if (x_flag || t_flag || d_flag) {
- indget = got_length = pksize;
- if (unzopen(getbyte, ZIP_ANY) != 0) return ziperr();
- }
- indput = 0;
- if (a_flag || d_flag) {
- if (zipcreat(putbyte, ZIP_PKW, pklevel) != 0) return ziperr();
- }
- }
- rblock = mblock = cblock;
- if (c_flag && !mblock) printbs(cblock = mblock = MAXBLOCK);
- wblock = 0;
- n_read = 0;
- return CORRECT;
- }
-
- void duptape(n)
- char *n;
- {
- register i;
- static char template[] = "XXXXXX";
-
- io_2nd = getbuf(BLKSIZE * (mblock ? mblock : MAXBLOCK));
- if (!io_2nd) done(ESMALL);
-
- i=strlen(n);
- while (i>0 &&
- #ifdef MSDOS
- n[i-1]!='\\' && n[i-1]!=':' &&
- #endif
- n[i-1]!='/') --i;
- scratch = salloc((int)(i + sizeof(template)));
- (void)strncpy(scratch, n, i);
- (void)strcpy (scratch+i, template);
- (void)mktemp (scratch);
- #ifdef UNIX
- hwrite = creat(scratch, 0666);
- #endif
- #ifdef MSDOS
- hwrite = open(scratch, O_CREAT+O_TRUNC+O_RDWR+O_BINARY, S_IREAD+S_IWRITE);
- #endif
- if (hwrite < 0) {
- (void)fprintf(myout, "Tar: can\'t create scratch file\n");
- done(EWRITE);
- }
- }
-
- void backtape()
- {
- register i;
-
- talign((long)n_read);
- if ((i = (int)(n_read / BLKSIZE % mblock)) == 0) i = mblock;
- if (!isfile) {
- register j;
-
- if ((*pback)(i)!=i) goto fault;
- if ((j=(*pread)(io_buf, BLKSIZE*rblock))<BLKSIZE) goto fault;
- n_read += j;
- }
- if ((*pback)(i) != i) goto fault;
- wblock = --rblock; indread = indwrite = 0;
- return;
- fault:
- (void)fprintf(myout, "Tar: tape seek fault\n");
- done(ERREAD);
- }
-
- void endtape()
- {
- nullblock(steptape());
- if (wblock) {
- if ((*pwrite)(io_2nd, BLKSIZE*((
- #ifdef MSDOS
- devtype == DEV_FILE || devtype == DEV_FLOP
- #else
- isfile
- #endif
- #ifdef USE_COMPRESS
- || pwrite == zwrite
- #endif
- || pwrite == gwrite)
- && wblock < mblock ? wblock : mblock)) < 0) {
- wrerror();
- }
- }
- #ifdef USE_COMPRESS
- if (pwrite == zwrite) {/* compression on output */
- if (cflush() < 0) wrerror();
- if (indput > 0) pkflush();
- } else
- #endif
- if (pwrite == gwrite) {/* zip compression */
- if (zipclose() == -1L) wrerror();
- if (indput > 0) pkflush();
- }
- if (hwrite >= 0 && close(hwrite)!=0) {
- (void)fprintf(myout, "Tar: tape close error\n");
- done(EWRITE);
- }
- }
-
- static int readbuf __ARGS__(( void ))
- {
- register i;
-
- if (mblock) {
- if ((i=(*pread)(io_buf, BLKSIZE*mblock)) < BLKSIZE || i%BLKSIZE != 0) {
- (void)fprintf(myout, rerror);
- if (i_flag) return -1;
- done(ERREAD);
- }
- n_read += i;
- nblock = i / BLKSIZE;
- } else {
- if ((i = (*pread)(io_buf, MAXBLOCK*BLKSIZE)) < BLKSIZE) {
- (void)fprintf(myout, rerror);
- if (i_flag) return -1;
- done(ERREAD);
- }
- n_read += i;
- talign((long)i);
- mblock = nblock = i / BLKSIZE;
- printbs(cblock = mblock);
- }
- rblock = 0;
- return 0;
- }
-
- struct header *readtape()
- {
- if (rblock>=nblock && readbuf()!=0) return NULL;
- indread = 0;
- return (struct header *)(io_buf + BLKSIZE * rblock++);
- }
-
- int readbyte()
- {
- register c;
-
- if (indread == 0) ++rblock; /* get 1-st byte - take all the block */
- if (rblock>nblock) {
- if (readbuf()!=0) return -1;
- rblock = 1; /* preserve 1-st block from readtape() */
- }
- c = ((unsigned char *)(io_buf + BLKSIZE * (rblock-1)))[indread];
- indread = (indread+1) & (BLKSIZE-1);
- return c;
- }
-
- void bacouple()
- /* return to the beginning of block after try to uncompress */
- {
- indread = 0; --rblock;
- }
-
- int readarch(h, length)
- int h; long length;
- {
- register i;
-
- while (length > 0) {
- if (rblock>=nblock && readbuf()!=0) return -1;
- if ((i = (nblock-rblock)*BLKSIZE) > length) i = (int)length;
- if (write(h, io_buf + rblock * BLKSIZE, i)!=i)
- extwrerr();
- rblock += (i + BLKSIZE-1) / BLKSIZE;
- length -= i;
- }
- indread = 0;
- return 0;
- }
-
- struct header *steptape()
- {
- if (!mblock) mblock = 1;
- if (wblock >= mblock) {
- if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
- wblock = 0;
- }
- indwrite = 0;
- return (struct header *)(io_2nd + BLKSIZE * wblock++);
- }
-
- void writebyte(c)
- int c;
- {
- if (indwrite == 0) ++wblock;
- if (wblock > mblock) {
- if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
- wblock = 1;
- }
- ((unsigned char *)(io_2nd + BLKSIZE * (wblock-1)))[indwrite] = c;
- indwrite = (indwrite+1) & (BLKSIZE-1);
- }
-
- int writearch(h, length, name)
- int h; long length; char *name;
- {
- register i; register j; register k;
- register char *p;
- register b;
-
- if (!mblock) mblock = 1;
-
- b = 0;
- while (length > 0) {
- if (wblock >= mblock) {
- if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
- wblock = 0;
- }
- k = BLKSIZE * (mblock-wblock);
- i = length < k ? (int)length : k;
- p = io_2nd + BLKSIZE * wblock;
- if ((j = read(h, p, i)) < 0) {
- (void)fprintf(myout, "Tar: error reading \'%s\'\n", name);
- done(ERREAD);
- }
- /* Calculate number of blocks affected */
- k = (BLKSIZE-1 + j) / BLKSIZE;
- wblock += k;
- b += k;
- /* Fill the slack area */
- for (p+=j, k=BLKSIZE*k-j; k>0; k--) *p++ = '\0';
- if (j != i) return b;
- length -= i;
- }
- if (wblock >= mblock) {
- if ((*pwrite)(io_2nd, BLKSIZE*mblock) < 0) wrerror();
- wblock = 0;
- }
- indwrite = 0;
- return b;
- }